-
Notifications
You must be signed in to change notification settings - Fork 3.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[microNPU] Add MergeConstants pass #12029
Conversation
Change-Id: I1ff51d8147fba8c66d442a370b9f058e9b2758d8
Change-Id: I29f68f83a73fa00ca34ed0ab2321c53c6b761137
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks @NicolaLancellotti !
I have a done a round of reviews. There are few things we should improve in the PR. See if you agree.
Also please consider adding docs for non-trivial functions.
We need to align with coding style of TVM : https://tvm.apache.org/docs/contribute/code_guide.html
(I have put a few specific comments to each type)
@@ -90,6 +90,8 @@ def lower_ethosu(sch, args, const_dict, name="main"): | |||
mod = tvm.tir.transform.RemoveNoOp()(mod) | |||
mod, const_dict = ethosu_passes.EncodeConstants(const_dict)(mod) | |||
mod = ethosu_passes.HoistAllocates()(mod) | |||
if not util.is_striping_enabled(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please leave a comment that MergeConstant pass currently does not support striped schedules and requires further investigation.
new_const_dict = {} | ||
for param in const_dict.keys(): | ||
new_const_dict[tvm.tir.IntImm("int64", param)] = tvm.nd.array(const_dict[param]) | ||
mod["main"] = mod["main"].with_attr("ethos-u.const-dict", new_const_dict) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit : lets stick to const_dict
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/tir/contrib/ethosu/passes.cc
Outdated
analyze = false; | ||
new_body = rewrite_prim_func_body(new_body); | ||
std::set<ObjectRef> params_to_delete{}; | ||
auto new_buffer_map{make_new_buffer_map(main_func->buffer_map, ¶ms_to_delete)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lets not use auto here.
it is fine to use auto when you can understand the type from just looking at the line. In this case, one need to look into the function.
Quote from from the following :
"For example, you can assume that the return type of make_unique() is obvious, but the return type of MyWidgetFactory() probably isn't."
Reference : https://google.github.io/styleguide/cppguide.html#Type_deduction
(Applies to all the lines)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/tir/contrib/ethosu/passes.cc
Outdated
|
||
// Rewrite new allocates | ||
for (auto it{copy_write_buffers.rbegin()}; it != copy_write_buffers.rend(); ++it) { | ||
if (auto buffer_opt = *it) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Lets use the type here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
Constants written to a buffer with local scope are not merged. | ||
""" | ||
|
||
def mergeConstantsPass(mod): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Style : this should be lower case. https://peps.python.org/pep-0008/#function-and-variable-names
(Only exception is the Passes because we want them aligned with C++ ones and I think the from API PoV the accessible pass function should be MergeConstants)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/tir/contrib/ethosu/passes.cc
Outdated
|
||
PrimFunc operator()(PrimFunc main_func, const Map<IntImm, runtime::NDArray>& const_dict) { | ||
// Analyze | ||
Stmt new_body{this->VisitStmt(main_func->body)}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is generally a not good practice to mix analysis and transformation in a single pass.
E.g. for analysis pass : (https://github.com/apache/tvm/blob/main/src/tir/usmp/analysis/extract_buffer_info.cc)
However, since this is simpler analysis we can keep the analysis pass internal to this source.
Can we break this out to a new pass (in this source file) that return the analysis information and run the sub-sequent pass to rewrite w/o resorting to a mode variable analyze ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/tir/contrib/ethosu/passes.cc
Outdated
if (op->size() <= 1) { | ||
return StmtExprMutator::VisitStmt_(op); | ||
} | ||
return analyze ? analyze_seq_stmt(op) : rewrite_seq_stmt(op); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refer to the above comment about seperation of analysis and transformation passes.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
src/tir/contrib/ethosu/passes.cc
Outdated
std::map<const VarNode*, Allocate> var_to_allocate{}; | ||
|
||
// Rewrite old allocates | ||
std::set<ObjectRef> buffer_vars{get_vars_for_written_copy_buffers()}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a ordered set here ? (Noting that ordered_set's access time is higher)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I switched to unordered_set.
src/tir/contrib/ethosu/passes.cc
Outdated
for (size_t i{0}; i < seq_stmt.size(); ++i) { | ||
Stmt stmt{seq_stmt[i]}; | ||
|
||
switch (get_stmt_type(stmt)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a default here.
Ref : https://google.github.io/styleguide/cppguide.html#Loops_and_Switch_Statements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a switch on an enumerated value, and all cases are covered. So we don't need a default, don't we?
src/tir/contrib/ethosu/passes.cc
Outdated
for (size_t i = 0; i < seq_stmt.size(); ++i) { | ||
Stmt stmt{seq_stmt[i]}; | ||
|
||
switch (get_stmt_type(stmt)) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We need a default here.
Ref : https://google.github.io/styleguide/cppguide.html#Loops_and_Switch_Statements
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is a switch on an enumerated value, and all cases are covered. So we don't need a default, don't we?
Change-Id: Iad59107d5abdec6b079c6fd4ab48c6bffbb5e0bb
Thanks for the review @manupa-arm! |
Change-Id: Ie5caf506337de01e169d6f422e4682eefbd93241
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM!
Thanks @NicolaLancellotti ! |
* [microNPU] Add MergeConstants pass Change-Id: I1ff51d8147fba8c66d442a370b9f058e9b2758d8 * Fix errors and warnings Change-Id: I29f68f83a73fa00ca34ed0ab2321c53c6b761137 * Address comments Change-Id: Iad59107d5abdec6b079c6fd4ab48c6bffbb5e0bb * Fix lint error Change-Id: Ie5caf506337de01e169d6f422e4682eefbd93241
* [microNPU] Add MergeConstants pass Change-Id: I1ff51d8147fba8c66d442a370b9f058e9b2758d8 * Fix errors and warnings Change-Id: I29f68f83a73fa00ca34ed0ab2321c53c6b761137 * Address comments Change-Id: Iad59107d5abdec6b079c6fd4ab48c6bffbb5e0bb * Fix lint error Change-Id: Ie5caf506337de01e169d6f422e4682eefbd93241
* [microNPU] Add MergeConstants pass Change-Id: I1ff51d8147fba8c66d442a370b9f058e9b2758d8 * Fix errors and warnings Change-Id: I29f68f83a73fa00ca34ed0ab2321c53c6b761137 * Address comments Change-Id: Iad59107d5abdec6b079c6fd4ab48c6bffbb5e0bb * Fix lint error Change-Id: Ie5caf506337de01e169d6f422e4682eefbd93241
* [microNPU] Add MergeConstants pass Change-Id: I1ff51d8147fba8c66d442a370b9f058e9b2758d8 * Fix errors and warnings Change-Id: I29f68f83a73fa00ca34ed0ab2321c53c6b761137 * Address comments Change-Id: Iad59107d5abdec6b079c6fd4ab48c6bffbb5e0bb * Fix lint error Change-Id: Ie5caf506337de01e169d6f422e4682eefbd93241
This pr adds a MergeConstants pass that looks for the constants used by each compute operator and merges them into a single buffer.
@manupa-arm @ekalda @lhutton1
cc @Mousius